﻿using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;

namespace FAQ_UI
{
	/// <summary>
	/// Toast.xaml 的交互逻辑
	/// </summary>
	public partial class Toast : UserControl
	{
		private Toast()
		{
			InitializeComponent();
			this.DataContext = this;
		}

		private Popup popup;

		private Toast(Window owner, string message, ToastOptions options = null)
		{
			Message = message;
			InitializeComponent();
			if (options == null)
			{
				options = new ToastOptions();
			}
			if (options != null)
			{
				Width = options.Width;
				Height = options.Height;
				Icon = options.Icon;
				Location = options.Location;
				Time = options.Time;
				Closed += options.Closed;
				Click += options.Click;
				Background = options.Background;
				Foreground = options.Foreground;
				FontStyle = options.FontStyle;
				FontStretch = options.FontStretch;
				FontSize = options.FontSize;
				FontFamily = options.FontFamily;
				FontWeight = options.FontWeight;
				IconSize = options.IconSize;
				BorderBrush = options.BorderBrush;
				BorderThickness = options.BorderThickness;
				HorizontalContentAlignment = options.HorizontalContentAlignment;
				VerticalContentAlignment = options.VerticalContentAlignment;
				CornerRadius = options.CornerRadius;
			}
			this.DataContext = this;
			if (owner == null)
			{
				this.owner = Application.Current.MainWindow;
			}
			else
			{
				this.owner = owner;
			}
			this.owner.Closed += Owner_Closed;
		}

		private void Owner_Closed(object sender, EventArgs e)
		{
			this.Close();
		}

		private event EventHandler<EventArgs> Closed;

		private void RaiseClosed(EventArgs e)
		{
			Closed?.Invoke(this, e);
		}

		private event EventHandler<EventArgs> Click;

		private void RaiseClick(EventArgs e)
		{
			Click?.Invoke(this, e);
		}

		private string Message
		{
			get { return (string)GetValue(MessageProperty); }
			set { SetValue(MessageProperty, value); }
		}

		private static readonly DependencyProperty MessageProperty =
			DependencyProperty.Register("Message", typeof(string), typeof(Toast), new PropertyMetadata(string.Empty));

		private CornerRadius CornerRadius
		{
			get { return (CornerRadius)GetValue(CornerRadiusProperty); }
			set { SetValue(CornerRadiusProperty, value); }
		}

		private static readonly DependencyProperty CornerRadiusProperty =
			DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(Toast), new PropertyMetadata(new CornerRadius(5)));

		private double IconSize
		{
			get { return (double)GetValue(IconSizeProperty); }
			set { SetValue(IconSizeProperty, value); }
		}

		private static readonly DependencyProperty IconSizeProperty =
			DependencyProperty.Register("IconSize", typeof(double), typeof(Toast), new PropertyMetadata(26.0));

		private new Brush BorderBrush
		{
			get { return (Brush)GetValue(BorderBrushProperty); }
			set { SetValue(BorderBrushProperty, value); }
		}

		private new static readonly DependencyProperty BorderBrushProperty =
			DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(Toast), new PropertyMetadata((Brush)new BrushConverter().ConvertFromString("#FFFFFF")));

		private new Thickness BorderThickness
		{
			get { return (Thickness)GetValue(BorderThicknessProperty); }
			set { SetValue(BorderThicknessProperty, value); }
		}

		private new static readonly DependencyProperty BorderThicknessProperty =
			DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(Toast), new PropertyMetadata(new Thickness(0)));

		private new Brush Background
		{
			get { return (Brush)GetValue(BackgroundProperty); }
			set { SetValue(BackgroundProperty, value); }
		}

		private new static readonly DependencyProperty BackgroundProperty =
			DependencyProperty.Register("Background", typeof(Brush), typeof(Toast), new PropertyMetadata((Brush)new BrushConverter().ConvertFromString("#2E2929")));

		private new HorizontalAlignment HorizontalContentAlignment
		{
			get { return (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty); }
			set { SetValue(HorizontalContentAlignmentProperty, value); }
		}

		private new static readonly DependencyProperty HorizontalContentAlignmentProperty =
			DependencyProperty.Register("HorizontalContentAlignment", typeof(HorizontalAlignment), typeof(Toast), new PropertyMetadata(HorizontalAlignment.Left));

		private new VerticalAlignment VerticalContentAlignment
		{
			get { return (VerticalAlignment)GetValue(VerticalContentAlignmentProperty); }
			set { SetValue(VerticalContentAlignmentProperty, value); }
		}

		private new static readonly DependencyProperty VerticalContentAlignmentProperty =
			DependencyProperty.Register("VerticalContentAlignment", typeof(VerticalAlignment), typeof(Toast), new PropertyMetadata(VerticalAlignment.Center));

		private new double Width
		{
			get { return (double)GetValue(WidthProperty); }
			set { SetValue(WidthProperty, value); }
		}

		private new static readonly DependencyProperty WidthProperty =
			DependencyProperty.Register("Width", typeof(double), typeof(Toast), new PropertyMetadata(200.0));

		private new double Height
		{
			get { return (double)GetValue(HeightProperty); }
			set { SetValue(HeightProperty, value); }
		}

		private new static readonly DependencyProperty HeightProperty =
			DependencyProperty.Register("Height", typeof(double), typeof(Toast), new PropertyMetadata(48.0));

		private ToastIcons Icon
		{
			get { return (ToastIcons)GetValue(IconProperty); }
			set { SetValue(IconProperty, value); }
		}

		private static readonly DependencyProperty IconProperty =
			DependencyProperty.Register("Icon", typeof(ToastIcons), typeof(Toast), new PropertyMetadata(ToastIcons.None));

		private int Time
		{
			get { return (int)GetValue(TimeProperty); }
			set { SetValue(TimeProperty, value); }
		}

		private static readonly DependencyProperty TimeProperty =
			DependencyProperty.Register("Time", typeof(int), typeof(Toast), new PropertyMetadata(2000));

		private ToastLocation Location
		{
			get { return (ToastLocation)GetValue(LocationProperty); }
			set { SetValue(LocationProperty, value); }
		}

		private static readonly DependencyProperty LocationProperty =
			DependencyProperty.Register("Location", typeof(ToastLocation), typeof(Toast), new PropertyMetadata(ToastLocation.Default));

		private Window owner;
		private Thread timer;

		public static void Show(string msg, ToastOptions options = null)
		{
			var toast = new Toast(null, msg, options);
			int time = toast.Time;
			ShowToast(toast, time);
		}

		public static void Show(Window owner, string msg, ToastOptions options = null)
		{
			var toast = new Toast(owner, msg, options);
			int time = toast.Time;
			ShowToast(toast, time);
		}

		private static void ShowToast(Toast toast, int time)
		{
			toast.popup = new Popup();
			toast.popup.Child = toast;
			toast.popup.IsOpen = true;
			toast.createTimer(time);
		}

		private void createTimer(int time)
		{
			timer = new Thread(() =>
			{
				Thread.Sleep(time);
				Dispatcher.Invoke(new Action(() =>
				{
					popup.IsOpen = false;
				}));
			})
			{ IsBackground = true };
			timer.Start();
		}

		public void Close()
		{
			if (timer != null)
			{
				timer.Interrupt();
				timer = null;
			}
			popup.IsOpen = false;
			owner.LocationChanged -= UpdatePosition;
			owner.SizeChanged -= UpdatePosition;
		}

		private void UpdatePosition(object sender, EventArgs e)
		{
			var up = typeof(Popup).GetMethod("UpdatePosition", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
			if (up == null || popup == null)
			{
				return;
			}
			SetPopupOffset(popup, this);
			up.Invoke(popup, null);
		}

		private void SetPopupOffset(object popup, Toast toast)
		{
		}

		private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs args)
		{ }
	}

	public enum ToastIcons
	{
		None,
		Information,//CheckSolid
		Error,//TimesSolid
		Warning,//ExclamationSolid
		Busy//ClockSolid
	}

	public enum ToastLocation
	{
		OwnerCenter,
		OwnerLeft,
		OwnerRight,
		OwnerTopLeft,
		OwnerTopCenter,
		OwnerTopRight,
		OwnerBottomLeft,
		OwnerBottomCenter,
		OwnerBottomRight,
		ScreenCenter,
		ScreenLeft,
		ScreenRight,
		ScreenTopLeft,
		ScreenTopCenter,
		ScreenTopRight,
		ScreenBottomLeft,
		ScreenBottomCenter,
		ScreenBottomRight,
		Default//OwnerCenter
	}

	public class ToastOptions
	{
		public double Width { get; set; } = 200;
		public double Height { get; set; } = 48;
		public int Time { get; set; } = 2000;
		public ToastIcons Icon { get; set; } = ToastIcons.None;
		public ToastLocation Location { get; set; } = ToastLocation.Default;
		public Brush Foreground { get; set; } = Brushes.White;
		public FontStyle FontStyle { get; set; } = SystemFonts.MessageFontStyle;
		public FontStretch FontStretch { get; set; } = FontStretches.Normal;
		public double FontSize { get; set; } = SystemFonts.MessageFontSize;
		public FontFamily FontFamily { get; set; } = SystemFonts.MessageFontFamily;
		public FontWeight FontWeight { get; set; } = SystemFonts.MenuFontWeight;
		public double IconSize { get; set; } = 26;
		public CornerRadius CornerRadius { get; set; } = new CornerRadius(5);
		public Brush BorderBrush { get; set; }
		public Thickness BorderThickness { get; set; } = new Thickness(1);
		public Brush Background { get; set; } = (Brush)new BrushConverter().ConvertFromString("#2E2929");
		public HorizontalAlignment HorizontalContentAlignment { get; set; } = HorizontalAlignment.Left;
		public VerticalAlignment VerticalContentAlignment { get; set; } = VerticalAlignment.Center;
		public EventHandler<EventArgs> Closed { get; internal set; }
		public EventHandler<EventArgs> Click { get; internal set; }
	}

	/*public class ToastIconConverter : IMultiValueConverter
	{
		public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
		{
			object value = values[0];
			object grid = values[1];
			object txt = values[2];
			Grid _grid = grid as Grid;
			TextBlock _txt = txt as TextBlock;
			if (value == null)
			{
				if (_grid != null)
				{
					_grid.ColumnDefinitions.RemoveAt(0);
				}
				if (_txt != null)
				{
					_txt.HorizontalAlignment = HorizontalAlignment.Center;
				}
				return PackIconFontAwesomeKind.None;
			}
			ToastIcons _value;
			try
			{
				_value = (ToastIcons)value;
			}
			catch
			{
				if (_grid != null)
				{
					_grid.ColumnDefinitions.RemoveAt(0);
				}
				if (_txt != null)
				{
					_txt.HorizontalAlignment = HorizontalAlignment.Center;
				}
				return PackIconFontAwesomeKind.None;
			}
			switch (_value)
			{
				case ToastIcons.Information:
					return PackIconFontAwesomeKind.CheckSolid;

				case ToastIcons.Error:
					return PackIconFontAwesomeKind.TimesSolid;

				case ToastIcons.Warning:
					return PackIconFontAwesomeKind.ExclamationSolid;

				case ToastIcons.Busy:
					return PackIconFontAwesomeKind.ClockSolid;
			}
			if (_grid != null)
			{
				_grid.ColumnDefinitions.RemoveAt(0);
			}
			if (_txt != null)
			{
				_txt.HorizontalAlignment = HorizontalAlignment.Center;
			}
			return PackIconFontAwesomeKind.None;
		}

		public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
		{
			throw new NotImplementedException();
		}
	}*/
}